package com.fortune.cat.config;

import com.fortune.cat.manager.ClassManager;
import com.fortune.cat.manager.DynamicRouteDefinitionManager;
import com.fortune.cat.manager.GatewayFilterManager;
import com.fortune.cat.resolver.AbstractKeyResolver;
import com.fortune.cat.resolver.CompositeKeyResolver;
import com.fortune.cat.route.VariableRouteDefinitionLocator;
import com.fortune.cat.route.VariableRouteDefinitionRouteLocator;
import org.I0Itec.zkclient.ZkClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.validation.Validator;

import java.util.List;

/**
 * @author zhaozeyang
 * @date 2019/4/18 19:31
 * @description
 */
@Configuration
public class GatewayConfig {


    @Bean
    public ClassManager groovyClassManager() {
        return new ClassManager();
    }

    @Bean
    GatewayFilterManager gatewayFilterManager(List<GatewayFilterFactory> gatewayFilterFactoryList) {
        return new GatewayFilterManager(gatewayFilterFactoryList);
    }


    @Bean
    public DynamicRouteDefinitionManager dynamicRouteDefinitionRepository(ZkClient zkClient,
                                                                          ClassManager classManager,
                                                                          GatewayFilterManager gatewayFilterManager) {
        return new DynamicRouteDefinitionManager(zkClient, classManager, gatewayFilterManager);
    }


    @Bean
    public RouteLocator variableRouteDefinitionRouteLocator(GatewayProperties properties,
                                                            List<RoutePredicateFactory> predicates,
                                                            VariableRouteDefinitionLocator routeDefinitionLocator,
                                                            GatewayFilterManager gatewayFilterManager,
                                                            @Qualifier("webFluxConversionService") ConversionService conversionService) {
        return new VariableRouteDefinitionRouteLocator(routeDefinitionLocator, predicates, properties, conversionService, gatewayFilterManager);
    }

    @Bean
    @Primary
    public AbstractKeyResolver compositeKeyResolver(List<AbstractKeyResolver> keyResolvers) {
         return new CompositeKeyResolver(keyResolvers);
    }

    @Bean
    @ConditionalOnMissingBean
    public RedisRateLimiter redisRateLimiter(
            ReactiveRedisTemplate<String, String> redisTemplate,
            @Qualifier(RedisRateLimiter.REDIS_SCRIPT_NAME) RedisScript<List<Long>> redisScript,
            Validator validator) {
        return new RedisRateLimiter(redisTemplate, redisScript, validator);
    }
}
